﻿using System;
using System.Collections.Generic;
using System.Data.Services;
using System.Data.Services.Common;
using System.Linq;
using System.ServiceModel.Web;
using System.Web;
using System.Web.Security;
using System.Web.Script.Serialization;
using ESN.Models;
using ESN.Helpers;
using System.Linq.Expressions;

namespace ESN
{
    [System.ServiceModel.ServiceBehavior(IncludeExceptionDetailInFaults = true)]
    public class QuizService : DataService<ESNQuizDbContext>
    {
        public static void InitializeService(DataServiceConfiguration config)
        {
            config.SetEntitySetAccessRule("*", EntitySetRights.All);
            //config.SetEntitySetAccessRule("EdmMetadatas", EntitySetRights.None);
            config.SetServiceOperationAccessRule("*", ServiceOperationRights.All);
            config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V3;
            config.UseVerboseErrors = true;
        }

        [ChangeInterceptor("Categories")]
        public void OnChangeCategories(Category cat, UpdateOperations operations)
        {
            Guid userid = new Guid();
            if (!PermissionHelper.IsAuthenticated(ref userid))
            {
                throw new DataServiceException(401, "User mus logged in to do this action.");
            }

            if (operations == UpdateOperations.Delete || operations == UpdateOperations.Change)
            {
                throw new DataServiceException(400, "Exercises can not be delete or change here! Use the operation at /QuizService.svc/DeleteCategories to delete it.");
            }

            if (operations == UpdateOperations.Add)
            {
                var check = from c in CurrentDataSource.Categories
                            where c.CatName == cat.CatName
                            select c;
                if (check.Count() > 0)
                {
                    throw new DataServiceException(400, "The Cateory is not available!");
                }
                cat.CatTime = DateTime.Now;
            }
        }

        [WebGet]
        public string DeleteCategories(int Id)
        {
            //var cat = new Category() {CatId = Id};
            try
            {
                CurrentDataSource.Categories.Remove(CurrentDataSource.Categories.Find(Id));
                CurrentDataSource.SaveChanges();
            }
            catch (Exception ex)
            {
                throw new DataServiceException(500, ex.Message);
            }

            return "The Caterory with Id = " + Id.ToString() + " has deleted succesfull!";
        }

        [QueryInterceptor("Exercises")]
        public Expression<Func<Exercise, bool>> OnQueryExercises()
        {
            Guid userid = new Guid();
            if (PermissionHelper.readAllExercises())
            {
                return e => true;
            }
            
            if (PermissionHelper.IsAuthenticated(ref userid))
            {
                return e => e.ExPublic == true || e.UserId == userid;
            }

            return e => e.ExPublic == true;
        }

        [WebGet]
        public bool DeleteExercises(int Id)
        {
            //var exc = new Exercise() { ExId = Id };
            Guid id = new Guid();

            if (!PermissionHelper.IsAuthenticated(ref id))
            {
                throw new DataServiceException(401, ESN.Languages.LangString.Load("must_loggin", "Error"));
            }
            var e = CurrentDataSource.Exercises.Find(Id);
            if (e.UserId != id)
            {
                throw new DataServiceException(400, ESN.Languages.LangString.Load("permission_cant", "Error"));
            }
            try
            {
                CurrentDataSource.Exercises.Remove(e);
                CurrentDataSource.SaveChanges();
            }
            catch (Exception ex)
            {
                throw new DataServiceException(500, ex.Message);
            }

            return true;
        }

        [ChangeInterceptor("Exercises")]
        public void OnChangeExercies(Exercise ex, UpdateOperations operations)
        {
            Guid userid = new Guid();
            if (!PermissionHelper.IsAuthenticated(ref userid))
            {
                throw new DataServiceException(401, "User mus logged in to do this action.");
            }

            if (operations == UpdateOperations.Delete)
            {
                throw new DataServiceException(400, "Exercises can not be delete here! Use the operation at /QuizService.svc/DeleteExercises instead.");
            }

            if (operations == UpdateOperations.Change)
            {
                if (ex.UserId != userid)
                {
                    throw new DataServiceException(401, "You dont have permission t take this action!");
                }
            }
            var parser = new JavaScriptSerializer();
            var dataErr = "Error with your data, close your browser and re-input.";
            List<Question> quesList = new List<Question>();
            List<List<string>> correctList = new List<List<string>>();
            try
            {
                quesList = parser.Deserialize<List<Question>>(ex.ExContent);
                correctList = parser.Deserialize<List<List<string>>>(ex.ExCorrect);
            }
            catch
            {
                throw new DataServiceException(400, dataErr);
            }
            for (int i = 0; i < quesList.Count; i++ )
            {
                var ques = quesList[i];
                switch (ques.type)
                {
                    case 0:
                        if(ques.numAns != ques.ans.Count || correctList[i].Count > 1)
                            throw new DataServiceException(400, dataErr);
                        break;
                    case 1:
                        if(ques.numAns != ques.ans.Count || correctList[i].Count > ques.ans.Count)
                            throw new DataServiceException(400, dataErr);
                        break;
                    case 2:
                        if(ques.numAns != ques.ansA.Count || ques.numAns != ques.ansB.Count || ques.numAns != correctList[i].Count)
                            throw new DataServiceException(400, dataErr);
                        break;
                    case 3:
                        if (ques.numAns != correctList[i].Count)
                            throw new DataServiceException(400, dataErr);
                        break;
                    case 4:
                        if (correctList[i].Count != 2 || Convert.ToInt32(correctList[i][0]) < Convert.ToInt32(correctList[i][1]))
                            throw new DataServiceException(400, dataErr);
                        break;
                }
            }

            ex.ExNumQues = quesList.Count;

            if (operations == UpdateOperations.Change)
            {
                ex.EditorId = userid;
            }
            else if (operations == UpdateOperations.Add)
            {
                ex.ExCreateTime = DateTime.Now;
                ex.UserId = userid;
            }
        }
    }
}
